﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace Cars
{
    public partial class NotifyForm : Form
    {
        System.Windows.Forms.Timer _closeTimer;
        bool _cancelFade = false;
        bool _fading = false;

        public NotifyForm()
        {
            InitializeComponent();
            _closeTimer = new System.Windows.Forms.Timer();
            MillisecondsToShow = 5000;
        }

        private void NotifyForm_Load(object sender, EventArgs e)
        {
            // only enable events if not in design mode
            if (!DesignMode)
            {
                _closeTimer.Tick += new EventHandler(CloseTimer_Tick);
                MouseMove += new MouseEventHandler(NotifyForm_MouseMove);

                this.Opacity = 0.0;
                int screenWidth = Screen.PrimaryScreen.WorkingArea.Width;
                int screenHeight = Screen.PrimaryScreen.WorkingArea.Height;
                this.Left = screenWidth - this.Width;
                this.Top = screenHeight - this.Height;
                FadeIn();
            }            
        }        

        protected void TimerStart()
        {
            if (!DesignMode)
                _closeTimer.Enabled = true;
        }

        protected void TimerStop()
        {
            if (!DesignMode)
                _closeTimer.Enabled = false;
        }

        public int MillisecondsToShow 
        {
            get
            {
                return _closeTimer.Interval;
            }
            set
            {
                bool oldShowTimerEnabled = _closeTimer.Enabled;
                TimerStop();
                try
                {
                    _closeTimer.Interval = value;
                }
                finally
                {
                    if (oldShowTimerEnabled)
                        TimerStart();
                }
            } 
        }

        void CloseTimer_Tick(object sender, EventArgs e)
        {
            _cancelFade = false;
            FadeOut();
        }

        int lastX = 0;
        int lastY = 0;

        // the mousemove event seems to happen even if the mouse is not moving
        // therefore i'll just to see if it has really moved or not
        private void NotifyForm_MouseMove(object sender, MouseEventArgs e)
        {
            if (DesignMode)
                return;

            if ((e.X == lastX) && (e.Y == lastY))
                return;

            // reset the fade timer so that the form won't disappear until
            // we leave the form or hold the mouse still for a while   
            if (!_fading)
                TimerStop();
            // cancel any current fade operation
            _cancelFade = true;

            lastX = e.X;
            lastY = e.Y;

            // make sure the timer gets restarted
            // UNLESS we are fading in/out in which case
            // the fade routine will leave it enabled
            if (!_fading)
                TimerStart();
        }

        protected void FadeIn()
        {
            _fading = true;
            try
            {
                TimerStop();

                float v1 = 1.0F;
                float v2 = 0.0F;
                float vd = 0.025F;                

                for (float v = v2; v <= v1; v += vd)
                {
                    if (_cancelFade)
                    {
                        // we are just rushing the fade in so that we
                        // immediately show it fully 
                        Opacity = v1;
                        Application.DoEvents();
                        break;
                    }
                    else
                    {
                        Opacity = v;
                        Application.DoEvents();
                        Thread.Sleep(25);
                    }
                }

                // start the timer
                TimerStart();
            }
            finally
            {
                _fading = false;
            }
        }

        protected void FadeOut()
        {
            _fading = true;
            try
            {
                TimerStop();

                float v1 = 1.0F;
                float v2 = 0.0F;
                float vd = 0.025F;

                for (float v = v1; v >= v2; v -= vd)
                {
                    if (_cancelFade)
                    {
                        // we are overriding fade out completely and
                        // making the form fully visible
                        Opacity = v1;
                        Application.DoEvents();
                        TimerStart();
                        return;
                    }
                    else
                    {
                        Opacity = v;
                        Application.DoEvents();
                        Thread.Sleep(50);
                    }
                }
                // if we got to the point where we are completely faded
                // just go ahead and close the form
                Close();
            }
            finally
            {
                _fading = false;
            }
        }
    }
}
